package com.hsck.order.kds.base.utils;


import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author isnoam
 * @package_name DataProcessor
 * @date 2024-09-12
 * DataProcessor 是一个通用工具类，可以处理任意类型的数据对象，
 * 通过反射提取对象的属性值，并根据指定字段返回对应的数据。
 *
 * @param <T> 泛型类型，表示处理的数据类型，要求为任意类型（Any）。
 */
public class DataProcessorToJava <T>{
    /**
     * 将给定对象转换为字段名-字段值的映射关系。
     *
     * 这个方法通过 Java 反射机制来动态获取对象的所有字段及其对应的值。
     *
     * @param obj T 类型的对象，它是当前处理的数据对象。
     * @return 返回一个 Map，其中键为属性名称，值为对应的属性值。
     * @throws IllegalAccessException 如果无法访问某个字段的值。
     */
    private Map<String, Object> toFieldMap(T obj) throws IllegalAccessException {
        Map<String, Object> fieldMap = new HashMap<>();

        // 获取对象类的所有声明字段
        Field[] fields = obj.getClass().getDeclaredFields();

        // 遍历所有字段，并将其字段名和字段值放入 Map 中
        for (Field field : fields) {
            field.setAccessible(true);  // 确保可以访问私有字段
            fieldMap.put(field.getName(), field.get(obj));
        }
        return fieldMap;
    }

    /**
     * 处理数据列表，提取指定字段名的数据并返回字段值的列表。
     *
     * 根据输入的字段名字符串，分割出字段列表，然后从数据对象的字段映射中
     * 按顺序提取每个对象中对应字段的值，最终返回一个包含多个字段值列表的集合。
     *
     * @param arrayFields 以逗号分隔的字段名称列表。
     * @param arrayData   要处理的数据对象列表，每个对象是泛型类型 T。
     * @return 返回一个二维列表，外层列表包含多个对象，每个对象对应的字段值按顺序存储在内层列表中。
     * @throws IllegalAccessException 如果无法访问对象中的字段值。
     */
    public List<List<Object>> processListData(String arrayFields, List<T> arrayData) throws IllegalAccessException {
        // 分割 arrayFields 得到字段名集合
        String[] fields = arrayFields.split(",");

        // 用于存储符合条件的字段值
        List<List<Object>> result = new ArrayList<>();

        // 遍历数据数组中的每个对象
        for (T dataObject : arrayData) {
            // 获取数据对象的字段映射
            Map<String, Object> fieldMap = toFieldMap(dataObject);
            List<Object> resultList = new ArrayList<>();

            // 遍历字段名集合，并按顺序获取对象中的字段值
            for (String field : fields) {
                field = field.trim(); // 去除空格
                resultList.add(fieldMap.get(field));
            }

            // 仅当 resultList 有内容时才将其添加到结果列表中
            if (!resultList.isEmpty()) {
                result.add(resultList);
            }
        }

        return result;
    }
}